#
#
# PyEMOF: An EMOF support for Python
#
# Copyright (C) 2004, 2007 Raphael Marvie 
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# http://www.fsf.org/licensing/licenses/gpl.html
#
# Author contact: raphael.marvie@lifl.fr
#
# Modified and adapted to conform with ECORE 2.0 by brenomachado@gmail.com


import emof.core

dtypes = dict()
types = list()
opposites = list()
supers = list()


# Begin -- grammar generated by Yapps
import sys, re
import yapps.yappsrt as yappsrt

class picoreScanner(yappsrt.Scanner):
    patterns = [
        ('"\\\\)"', re.compile('\\)')),
        ("','", re.compile(',')),
        ('"\\\\("', re.compile('\\(')),
        ('"operation"', re.compile('operation')),
        ('"isUnique"', re.compile('isUnique')),
        ('"isReadOnly"', re.compile('isReadOnly')),
        ('"isComposite"', re.compile('isComposite')),
        ('"\\\\]"', re.compile('\\]')),
        ('".."', re.compile('..')),
        ('"\\\\["', re.compile('\\[')),
        ('":"', re.compile(':')),
        ('"attribute"', re.compile('attribute')),
        ('";"', re.compile(';')),
        ('"primitive"', re.compile('primitive')),
        ('"isAbstract"', re.compile('isAbstract')),
        ('","', re.compile(',')),
        ('"extends"', re.compile('extends')),
        ('"class"', re.compile('class')),
        ('"}"', re.compile('}')),
        ('"{"', re.compile('{')),
        ('"package"', re.compile('package')),
        ('[ \t\r\n]+', re.compile('[ \t\r\n]+')),
        ('//.*?\r?\n', re.compile('//.*?\r?\n')),
        ('ID', re.compile('[a-zA-Z][a-zA-Z0-9_]*')),
        ('LOWER', re.compile('(0|1)')),
        ('UPPER', re.compile('(1|\\*)')),
        ('END', re.compile('$')),
    ]
    def __init__(self, str):
        yappsrt.Scanner.__init__(self,None,['[ \t\r\n]+', '//.*?\r?\n'],str)

class picore(yappsrt.Parser):
    Context = yappsrt.Context
    def spec_stmt(self, _parent=None):
        _context = self.Context(_parent, self._scanner, self._pos, 'spec_stmt', [])
        rep = emof.core.Repository()
        while self._peek('END', '"package"') == '"package"':
            package_stmt = self.package_stmt(_context)
            rep.Package.append(package_stmt)
        if self._peek() not in ['END', '"package"']:
            raise yappsrt.SyntaxError(charpos=self._scanner.get_prev_char_pos(), context=_context, msg='Need one of ' + ', '.join(['END', '"package"']))
        END = self._scan('END')
        return rep

    def package_stmt(self, _parent=None):
        _context = self.Context(_parent, self._scanner, self._pos, 'package_stmt', [])
        self._scan('"package"')
        ID = self._scan('ID')
        self._scan('"{"')
        p = emof.core.Package() ; p.name = ID
        while self._peek('"}"', '"class"', '"primitive"', '"package"') != '"}"':
            _token = self._peek('"class"', '"primitive"', '"package"')
            if _token == '"class"':
                class_stmt = self.class_stmt(_context)
                p.ownedType.append(class_stmt)
            elif _token == '"primitive"':
                primitive_stmt = self.primitive_stmt(_context)
                p.ownedType.append(primitive_stmt)
            else: # == '"package"'
                package_stmt = self.package_stmt(_context)
                p.nestedPackage.append(package_stmt)
        if self._peek() not in ['"}"', '"class"', '"primitive"', '"package"']:
            raise yappsrt.SyntaxError(charpos=self._scanner.get_prev_char_pos(), context=_context, msg='Need one of ' + ', '.join(['"}"', '"class"', '"primitive"', '"package"']))
        self._scan('"}"')
        return p

    def class_stmt(self, _parent=None):
        _context = self.Context(_parent, self._scanner, self._pos, 'class_stmt', [])
        self._scan('"class"')
        ID = self._scan('ID')
        c = emof.core.Class() ; c.name = ID ; dtypes[ID] = c
        if self._peek('"extends"', '"isAbstract"', '","', '"{"') == '"extends"':
            self._scan('"extends"')
            ID = self._scan('ID')
            supers.append((c, ID))
            while self._peek('","', '"isAbstract"', '"{"') == '","':
                self._scan('","')
                ID = self._scan('ID')
                supers.append((c, ID))
            if self._peek() not in ['","', '"isAbstract"', '"{"']:
                raise yappsrt.SyntaxError(charpos=self._scanner.get_prev_char_pos(), context=_context, msg='Need one of ' + ', '.join(['","', '"isAbstract"', '"{"']))
        if self._peek('"isAbstract"', '"{"') == '"isAbstract"':
            self._scan('"isAbstract"')
            c.isAbstract = True
        self._scan('"{"')
        while self._peek('"}"', '"attribute"', '"operation"') != '"}"':
            _token = self._peek('"attribute"', '"operation"')
            if _token == '"attribute"':
                attr_stmt = self.attr_stmt(_context)
                c.ownedAttribute.append(attr_stmt)
            else: # == '"operation"'
                operation_stmt = self.operation_stmt(_context)
                c.ownedOperation.append(operation_stmt)
        if self._peek() not in ['"}"', '"attribute"', '"operation"']:
            raise yappsrt.SyntaxError(charpos=self._scanner.get_prev_char_pos(), context=_context, msg='Need one of ' + ', '.join(['"}"', '"attribute"', '"operation"']))
        self._scan('"}"')
        return c

    def primitive_stmt(self, _parent=None):
        _context = self.Context(_parent, self._scanner, self._pos, 'primitive_stmt', [])
        self._scan('"primitive"')
        ID = self._scan('ID')
        pt = emof.core.PrimitiveType() ; pt.name = ID ; dtypes[ID] = pt
        self._scan('";"')
        return pt

    def attr_stmt(self, _parent=None):
        _context = self.Context(_parent, self._scanner, self._pos, 'attr_stmt', [])
        self._scan('"attribute"')
        ID = self._scan('ID')
        p = emof.core.Property() ; p.name = ID
        self._scan('":"')
        ID = self._scan('ID')
        types.append((p, ID))
        if self._peek('"\\\\["', '"isComposite"', '"isReadOnly"', '"isUnique"', '";"') == '"\\\\["':
            self._scan('"\\\\["')
            LOWER = self._scan('LOWER')
            self._scan('".."')
            UPPER = self._scan('UPPER')
            self._scan('"\\\\]"')
            p.lower = LOWER ; p.upper = UPPER
        while self._peek('";"', '"isComposite"', '"isReadOnly"', '"isUnique"') != '";"':
            _token = self._peek('"isComposite"', '"isReadOnly"', '"isUnique"')
            if _token == '"isComposite"':
                self._scan('"isComposite"')
                p.isComposite = True
            elif _token == '"isReadOnly"':
                self._scan('"isReadOnly"')
                p.isReadOnly = True
            else: # == '"isUnique"'
                self._scan('"isUnique"')
                p.isUnique = True
        if self._peek() not in ['";"', '"isComposite"', '"isReadOnly"', '"isUnique"']:
            raise yappsrt.SyntaxError(charpos=self._scanner.get_prev_char_pos(), context=_context, msg='Need one of ' + ', '.join(['"isComposite"', '"isReadOnly"', '"isUnique"', '";"']))
        self._scan('";"')
        return p

    def operation_stmt(self, _parent=None):
        _context = self.Context(_parent, self._scanner, self._pos, 'operation_stmt', [])
        self._scan('"operation"')
        ID = self._scan('ID')
        o = emof.core.Operation() ; o.name = ID
        self._scan('"\\\\("')
        if self._peek('"\\\\)"', 'ID', "','") == 'ID':
            param_stmt = self.param_stmt(_context)
            o.ownedParameter.append(param_stmt)
            while self._peek("','", '"\\\\)"') == "','":
                self._scan("','")
                param_stmt = self.param_stmt(_context)
                o.ownedParameter.append(param_stmt)
            if self._peek() not in ["','", '"\\\\)"']:
                raise yappsrt.SyntaxError(charpos=self._scanner.get_prev_char_pos(), context=_context, msg='Need one of ' + ', '.join(["','", '"\\\\)"']))
        self._scan('"\\\\)"')
        self._scan('";"')
        return o

    def param_stmt(self, _parent=None):
        _context = self.Context(_parent, self._scanner, self._pos, 'param_stmt', [])
        ID = self._scan('ID')
        self._scan('":"')
        p = emof.core.Parameter() ; p.name = ID
        ID = self._scan('ID')
        types.append((p, ID)) ; return p


def parse(rule, text):
    P = picore(picoreScanner(text))
    return yappsrt.wrap_error_reporter(P, rule)

# End -- grammar generated by Yapps



def postprocessing():
    for ref, id in types:
        ref.type = dtypes[id]
    for ref, id in supers:
        ref.superClass.append(dtypes[id])

def process(filename):
    line = open(filename).read()
    rep = parse('spec_stmt', line)
    postprocessing()
    return rep
